package com.cw.util;

import com.alibaba.fastjson.JSON;
import com.cw.annotation.NeedMerge;
import com.cw.dto.RowRangeDto;
import com.cw.dto.WorkSumReportDTO;
import com.cw.entity.SysUser;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * excel合并工具包
 * @author: ly
 * @date: 2021/06/16 10:30
 **/
public class ExcelUtil {
    /**
     * @Author: TheBigBlue
     * @Description: 添加合并策略
     * @Date: 2020/3/16
     * @Param:
     * @return:
     **/
    public static Map<String, List<RowRangeDto>> addMerStrategy(List<WorkSumReportDTO> workSumReportDTOList) {
        Map<String, List<RowRangeDto>> strategyMap = new HashMap<>();
        WorkSumReportDTO preWorkSumReportDTO = null;
        for (int i = 0; i < workSumReportDTOList.size(); i++) {
            WorkSumReportDTO currDto = workSumReportDTOList.get(i);
            if (preWorkSumReportDTO != null) {
                //从第二行开始判断是否需要合并
                if (currDto.getOperName().equals(preWorkSumReportDTO.getOperName())) {
                    //如果坐席人员一样，则可合并坐席人员一列
                    fillStrategyMap(strategyMap, "0", i);
                }
            }
            preWorkSumReportDTO = currDto;
        }
        return strategyMap;
    }

    /**
     * @Author: TheBigBlue
     * @Description: 新增或修改合并策略map
     * @Date: 2020/3/16
     * @Param:
     * @return:
     **/
    private static void fillStrategyMap(Map<String, List<RowRangeDto >> strategyMap, String key, int index) {
        List<RowRangeDto > workSumReportDTOList = strategyMap.get(key) == null ? new ArrayList<>() : strategyMap.get(key);
        boolean flag = false;
        for (RowRangeDto dto : workSumReportDTOList) {
            //分段list中是否有end索引是上一行索引的，如果有，则索引+1
            if (dto.getEnd() == index) {
                dto.setEnd(index + 1);
                flag = true;
            }
        }
        //如果没有，则新增分段
        if (!flag) {
            workSumReportDTOList.add(new RowRangeDto(index, index + 1));
        }
        strategyMap.put(key, workSumReportDTOList);
    }


    /**
     * 计算出需要合并的坐标,提供给EasyExcel
     * @param list 需要计算合并单元的集合
     * @author ly
     * @date 2021/8/12 14:29
     * @return java.util.Map<java.lang.String,java.util.List<com.cw.dto.RowRangeDto>>
     */
    public static Map<String, List<RowRangeDto>> reflectionAddMerStrategy(List<?> list) {
        if (CollectionUtils.isEmpty(list)) { return null; }

        Map<String, List<RowRangeDto>> strategyMap = new HashMap<>();
        //集合内部的对象
        Object entity = null;
        //循环集合内部对象
        for (int i = 0; i < list.size(); i++) {
            Object collectionEntity = list.get(i);
            if (entity == null) {
                entity = collectionEntity; continue;
            }

            //搞到对象的字节码文件
            Class<?> aClass = collectionEntity.getClass();
            //获取对象中所有声明的字段public private protected都获取
            Field[] declaredFields = aClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                //是否存在需要合并的注解
                boolean annotationPresent = declaredField.isAnnotationPresent(NeedMerge.class);
                //不存在需要合并的注解直接下个循环
                if (!annotationPresent) { continue; }
                String columnName = declaredField.getName();
                NeedMerge needMerge = declaredField.getAnnotation(NeedMerge.class);
                String inExcelIndex = needMerge.inExcelIndex();
                try {
                    //通过getter方法获取循环内的值
                    String methodName = "get" + upperFirstLetter(columnName);
                    Method declaredMethod = aClass.getDeclaredMethod(methodName);
                    Object value = declaredMethod.invoke(collectionEntity);

                    //获取外部循环的对象的字节码文件,在获取他对应的值
                    Class<?> entityClass = entity.getClass();
                    Method entityMethod = entityClass.getDeclaredMethod(methodName);
                    Object entityValue = entityMethod.invoke(entity);

                    if (value == null) { continue; }
                    if (entityValue == null) { continue; }

                    if (entityValue.equals(value) || entityValue.toString().equals(value.toString())) { fillStrategyMap(strategyMap, inExcelIndex, i); }
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
            entity = collectionEntity;
        }
        return strategyMap;
    }


    /**
     * 首个字母大写
     * @param name 需要处理的字符串
     * @author ly
     * @date 2021/8/12 15:28
     * @return java.lang.String
     */
    private static String upperFirstLetter(String name) {
        //因为lombok生成出来的getter setter方法,是首字母大写变量名
        //为了我们严谨的反射机制小朋友能找到它,这里给他首字母大写
        return name.substring(0, 1).toUpperCase() + name.substring(1);
    }

    public static void main(String[] args) {
        List<SysUser> sysUsers = new ArrayList<>();
        SysUser sysUser4 = new SysUser();
        sysUser4.setUserId("1");
        SysUser sysUser = new SysUser();
        sysUser.setUserId("1");
        SysUser sysUser1 = new SysUser();
        sysUser1.setUserId("1");
        SysUser sysUser2 = new SysUser();
        sysUser2.setUserId("1");
        SysUser sysUser3 = new SysUser();
        sysUser3.setUserId("5");
        sysUsers.add(sysUser2);
        sysUsers.add(sysUser1);
        sysUsers.add(sysUser);
        sysUsers.add(sysUser3);
        sysUsers.add(sysUser4);

        Map<String, List<RowRangeDto>> stringListMap = reflectionAddMerStrategy(sysUsers);
        System.out.println(JSON.toJSONString(stringListMap));
    }
}
